#include<stdio.h>
#include<stdlib.h>
#define MAX 10   //最大进程数
int Time;   //时间片
int process_amount;  //进程数量
int current_number = 0;   //当前执行的“号码牌”
int index = 0;       //就绪队列要发的“号码牌”，初始值为0
struct PCB
{
    char name[10];   //进程名字
    int arrival_time;   //到达时间
    int service_time;   //服务时间
    int completion_time;   //完成时刻
    int sign_completion;  //标志是否完成调用，0表示没完成，1表示完成
    int remaining_time;  //剩余服务时间
    int number;          //进程在就绪队列里的“号码牌”
}process[MAX];

void input()     //初始化进程的信息
{
    int i;
    printf("请输入时间片：\n");
    scanf("%d",&Time);
    printf("请输入进程名称、到达时间、服务时间：\n");
for(i = 0; i < process_amount; i ++)      
    { 
        printf("%d号进程:\n",i+1);
        scanf("%s%d%d",process[i].name,&process[i].arrival_time,&process[i].service_time);
        printf("\n");
        process[i].remaining_time = process[i].service_time;
        process[i].sign_completion = 0;
        process[i].number = 0;       //“号码牌”初始为0
    }
}

void BubbleSort()    //冒泡排序算法对进程抵达时间先后排序
{
    int i,j,n = process_amount;
    for(i = 0; i < n - 1; i++)         
    for(j = 0; j < n - 1 - i; j++) 
    {
        if(process[j].arrival_time > process[j+1].arrival_time)
        {
            process[n] = process[j+1];
            process[j+1] = process[j];
            process[j] = process[n];

        }
    }
}

void RunProcess()     //时间片轮转调用过程
{
    int time = process[0].arrival_time;      //给当前时间赋初值 
    int sum = 0;					//记录完成的进程数 
    int i,j;
    while(sum < process_amount)
    {  
    for(i = 0;  i < process_amount; i++)
        if(current_number == process[i].number && process[i].sign_completion == 0)
        {
            if(process[i].remaining_time <= Time)    //剩余服务时间少于等于一个时间片 
            {
            time = time + process[i].remaining_time;
            process[i].sign_completion = 1;
            process[i].completion_time = time;
            process[i].remaining_time = 0;
			printf("%s ",process[i].name);          
			sum++;
			current_number++;
			for(j = i + 1; j < process_amount; j++)     //检测后面有没有新进程到达
				if(process[j].arrival_time <= time && process[j].number == 0)
				{
					index++;
					process[j].number = index;
				}
		 	}
		 	
		 	else if(process[i].remaining_time > Time)//剩余服务时间大于一个时间片 
		 	{
		 		time = time + Time;
				process[i].remaining_time -= Time;
				printf("%s ",process[i].name);
				current_number++;
				for(j = i + 1; j < process_amount; j++)    //检测后面有没有新进程到达
				if(process[j].arrival_time <= time && process[j].number == 0)
				{
					index++;
					process[j].number = index;
				}
				index++;
				process[i].number = index;
			} 
		}
	if(index < current_number && sum < process_amount)   // 还有没执行的进程，且没进入就绪队列 
	{
	for(i = 0; i <= process_amount; i++)
		if(process[i].sign_completion == 0) 
		{
			time = process[i].arrival_time;
			index++;
			process[i].number = index;
			break;
		}
	}
}
}

void output()   //打印信息
{
	int i;
	printf("程序名 到达时间 服务时间 完成时间 周转时间  带权周转时间\n");
	for(i = 0; i < process_amount; i++)
	{
		float weight_time = (float)(process[i].completion_time - process[i].arrival_time)/process[i].service_time;
		printf("  %s\t  %d\t   %d\t    %d\t     %d\t\t%.2f\n",process[i].name,process[i].arrival_time,process[i].service_time,
			process[i].completion_time,process[i].completion_time-process[i].arrival_time,weight_time);
	}
}

int main()
{
	int f;
	printf("模拟时间片轮转法实现进程调度\n");
	printf("请输入总进程数：\n");
	scanf("%d",&process_amount);
	input();
	BubbleSort();
	printf("进程运行顺序：\n");
	RunProcess();
	printf("\n");
	output();
	printf("\n");
	system("pause");
	return 0;
}
